package org.example.config;

import org.example.service.UserServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;

import javax.sql.DataSource;

/**
 * @Auther: GongXl
 * @Date: 2021/3/9 13:42
 * @Description:
 */
//@Configuration
//@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    MyAccessDeniedHandler myAccessDeniedHandler;
    @Autowired
    UserServiceImpl userServiceImpl;
    @Autowired
    DataSource dataSource;
    @Autowired
    PersistentTokenRepository tokenRepository;
    @Override
    protected void configure(HttpSecurity http) throws Exception {
//        表单提交允许
        http.formLogin().permitAll()
                //自定义登录页面
                .loginPage("/showLogin")
                //自定真实的处理逻辑方法（和controller中自定义的/login方法没有关系，是调用security中的方法）默认是login
                .loginProcessingUrl("/login")
                //登录成功后请求的地址
                .successForwardUrl("/toMain")
                //这种方式可以调到外边或前后端分离项目返回json数据
//                .successHandler(new MyAuthenticationSuccessHandler("http://www.baidu.com"))
                //失败跳转的页面
//        .failureForwardUrl("/toError")
//                自定义异常跳转路径
                .failureHandler(new MyAuthenticationFailureHandler("/error.html"))
                //可自定义默认用户名密码
        .usernameParameter("username")
        .passwordParameter("password");
        //授权（地址先经过SpringSecurity的HttpSecurity，再经过资源服务器的HttpSecurity）
        http.authorizeRequests()
//                放行/oauth，因为授权服务器的断点是/oauth
                .antMatchers("/oauth/**","/login/**","/logout/**").permitAll()
                //放行登录页面
                .antMatchers("/showLogin").permitAll()
                //放行失败页面
                .antMatchers("/error.html").permitAll()
//                根据权限匹配，任意一个就可以
                .antMatchers("/main1.html").hasAnyAuthority("admin","admin1")
//                放行所有目录的所有jpg文件，双**
                .antMatchers("/**/*.jpg").permitAll()
                //角色验证,加过这个条件，不管上面什么权限，这个角色必须满足才可访问
                .antMatchers("/main1.html").hasAnyRole("role1")
                //所有非放行的请求都必须认证（登录）后才可访问
                .anyRequest().authenticated();
//        自定义放行逻辑
//                .anyRequest().access("@myServiceImpl.hasPermission(request,authentication)");

        http.exceptionHandling().accessDeniedHandler(myAccessDeniedHandler);
//    记住我
        http.rememberMe()
                //页面字段
                .rememberMeParameter("remember-me")
                //设置失效时间
                .tokenValiditySeconds(9191919)
//                自定义功能实现逻辑
//                .rememberMeServices()
//                自定义逻辑
                .userDetailsService(userServiceImpl)
//                指定存储位置
                .tokenRepository(tokenRepository);
        //退出登录
        http.logout()
                //自定义的登出页面url
                .logoutUrl("/logout")
//                退出登录成功的跳转的页面
                .logoutSuccessUrl("/login.html");
        //关闭csrf防护（要么不允许访问）
//        http.csrf().disable();
    }
    @Bean
    public PersistentTokenRepository tokenRepository(){
        JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl();
        tokenRepository.setDataSource(dataSource);
//        tokenRepository.setCreateTableOnStartup(true);
        return tokenRepository;
    }
    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
    /*@Bean
    public PasswordEncoder pw(){
        return new BCryptPasswordEncoder();
    }*/
}